/*
	Copyright (c) 2010 <copyright holders>
	This source code is licensed under The MIT License,
	see the file LICENSE for details.
	*/

#include "MenuGUI.hpp"

#include <boost/date_time.hpp>
#include <boost/filesystem.hpp>
#include <QuickGUI.h>

#include "Game.hpp"
#include "FileDefs.hpp"
#include "MenuNetLogic.hpp"
#include "MessageFile.hpp"
#include "gen/netmsg.pb.h"
#include "gen/savemsg.pb.h"
#include "WorldManager.hpp" //TODO: get rid of this dep
#include "WorldPresentation.hpp"
#include "BundleInfo.hpp"

using namespace QuickGUI;

namespace spelprog2 {
namespace gui {

const int PLAYER_TAB_INDEX = 0;
const int SCENARIO_TAB_INDEX = 1;

MenuGUI::MenuGUI(Game & game, Ogre::SceneManager & sceneMan) : GameGUI(sceneMan, game.getViewport()),
    game_(game),
    replayPaths_(),
    inLobby_(false),
    connectAsHost_(false)
{
    initMenuSheet();
    initLobbySheet();
    initReplaySheet();
    initConnectWindow();

    getManager().setActiveSheet(&get<Sheet>("menuSheet"));
}

MenuGUI::~MenuGUI()
{
    //destroy text boxes manually, QuickGUI crashes otherwise
    destroy("connectWindow.addrBox");
    destroy("connectWindow.portBox");
    destroy("connectWindow.usernameBox");
    destroy("connectWindow.passwordBox");
    destroy("lobbySheet.chatBox");
}

void MenuGUI::registerNetListeners()
{
    using namespace net_logic;
    net::Net & net = game_.getNetworking();
    net.addMsgListener<netmsg::ChatMessage> (MenuNetListener::Pointer(new HandleChatMessage(*this)));
    net.addMsgListener<netmsg::StartGame>   (MenuNetListener::Pointer(new HandleStartGame(*this)));
}

void MenuGUI::unregisterNetListeners()
{
    using namespace net_logic;
    net::Net & net = game_.getNetworking();
    net.removeMsgListenersOfType<netmsg::ChatMessage>();
    net.removeMsgListenersOfType<netmsg::StartGame>();
}

void MenuGUI::initMenuSheet()
{
    const FloatRect allSheet = { 0.25f, 0.1f, 0.75f, 0.9f };
    const QuickGUI::Size maxSheetSize(1024, 768.0f);
    Sheet & sheet = *createSheet(allSheet, AA_CENTER, AA_CENTER, &maxSheetSize);
    add("menuSheet", sheet);

    //create back panel
    Panel & backPanel = *sheet.createPanel(sheet.getClientDimensions());
    const QuickGUI::Rect backDim = backPanel.getClientDimensions();

    //calculate button size and positions (it's supposed to look good regardless of screen res and with different NUM_BUTTONS)
    const int NUM_BUTTONS = 4;
    const float allocatedHeight = backDim.size.height * 0.5f / NUM_BUTTONS;
    const QuickGUI::Size buttonSize = QuickGUI::Size(backDim.size.width * 0.8f, (16.0f + allocatedHeight) / 2);
    const float buttonYChange = allocatedHeight * 1.2f;
    QuickGUI::Point buttonPos[NUM_BUTTONS];
    for (int i = 0; i < NUM_BUTTONS; ++i) {
       buttonPos[i].x = (backDim.size.width - buttonSize.width) / 2;
       buttonPos[i].y = (i + 1) * buttonYChange;
    }

    //create buttons
    Button & launchTestButton = *backPanel.createButton("Launch Local Test", QuickGUI::Rect(buttonPos[0], buttonSize));
    launchTestButton.addWidgetEventHandler(WIDGET_EVENT_MOUSE_BUTTON_UP, &MenuGUI::clickLaunchTestButton, this);

    Button & toLobbyButton = *backPanel.createButton("Enter Multiplayer", QuickGUI::Rect(buttonPos[1], buttonSize));
    toLobbyButton.addWidgetEventHandler(WIDGET_EVENT_MOUSE_BUTTON_UP, &MenuGUI::clickLobbyButton, this);

    Button & toReplayButton = *backPanel.createButton("View Replays", QuickGUI::Rect(buttonPos[2], buttonSize));
    toReplayButton.addWidgetEventHandler(WIDGET_EVENT_MOUSE_BUTTON_UP, &MenuGUI::clickReplayButton, this);

    Button & exitButton = *backPanel.createButton("Exit (Loser!!!)", QuickGUI::Rect(buttonPos[3], buttonSize));
    exitButton.addWidgetEventHandler(WIDGET_EVENT_MOUSE_BUTTON_UP, &MenuGUI::clickExitButton, this);
}

void MenuGUI::initLobbySheet()
{
    DescManager & descMan = DescManager::getSingleton();
    std::vector<TextSegment> seg;
    seg.push_back(TextSegment());

    // Sheet ==================================================================

    const FloatRect allSheet = { 0.05f, 0.05f, 0.95f, 0.95f };
    const QuickGUI::Size maxSheetSize(1024, 768.0f);
    Sheet & sheet = *createSheet(allSheet, AA_CENTER, AA_CENTER, &maxSheetSize);
    add("lobbySheet", sheet);
    QuickGUI::Rect sheetDim = sheet.getClientDimensions();
    sheetDim.position = QuickGUI::Point::ZERO;

    // Coordinates of base widgets directly on sheet ==========================

    const FloatRect viewTabRect = { 0.34f, 0.0f, 0.75f, 1.0f };
    const FloatRect chatPanelRect = { 0.0f, 0.15f, 0.34f, 1.0f };
    const FloatRect buttonsPanelRect = { 0.0f, 0.05f, 0.34f, 0.15f };
    const FloatRect smallMapPanelRect = { 0.75f, 0.15f, 1.0f, 0.45f };
    const FloatRect smallSettingsPanelRect = { 0.75f, 0.55f, 1.0f, 0.95f };

    
    // Small map panel (on side) ==============================================

    Panel & smallMapPanel = *sheet.createPanel(layoutRect(smallMapPanelRect, sheetDim));
    add("lobbySheet.smallMapPanel", smallMapPanel);
    QuickGUI::Rect smallMapPanelDim = smallMapPanel.getClientDimensions();
    smallMapPanelDim.position = QuickGUI::Point::ZERO;

    const FloatRect smallMapLabelRect = { 0.05f, 0.05f, 0.95f, 0.15f };
    add("lobbySheet.smallMapLabelRect", smallMapPanel.createLabel("Map: The Bacterium of Aerium", //shall be dynamically modified
        layoutRect(smallMapLabelRect, smallMapPanelDim)));


    // Small settings panel (on side) =========================================

    Panel & smallSettingsPanel = *sheet.createPanel(layoutRect(smallSettingsPanelRect, sheetDim));
    add("lobbySheet.smallSettingsPanel", smallSettingsPanel);
    QuickGUI::Rect smallSettingsPanelDim = smallSettingsPanel.getClientDimensions();
    smallSettingsPanelDim.position = QuickGUI::Point::ZERO;

    const FloatRect smallSettingsLabelRect = { 0.05f, 0.05f, 0.95f, 0.10f };
    smallSettingsPanel.createLabel("Settings:", layoutRect(smallSettingsLabelRect, smallSettingsPanelDim));

    
    // Buttons panel ==========================================================

    Panel & buttonsPanel = *sheet.createPanel(layoutRect(buttonsPanelRect, sheetDim));
    QuickGUI::Rect buttonsPanelDim = buttonsPanel.getClientDimensions();
    buttonsPanelDim.position = QuickGUI::Point::ZERO;

    const FloatRect startButtonRect = { 0.0, 0.0f, 0.5f, 1.0f };
    const FloatRect connectButtonRect = { 0.5f, 0.0f, 1.0f, 1.0f };

    Button & startButton = *buttonsPanel.createButton("Host...", layoutRect(startButtonRect, buttonsPanelDim));
    add("lobbySheet.startButton", startButton);
    startButton.addWidgetEventHandler(WIDGET_EVENT_MOUSE_BUTTON_UP, &MenuGUI::clickConnectStartButton, this);

    Button & connectButton = *buttonsPanel.createButton("Connect...", layoutRect(connectButtonRect, buttonsPanelDim));
    add("lobbySheet.connectButton", connectButton);
    connectButton.addWidgetEventHandler(WIDGET_EVENT_MOUSE_BUTTON_UP, &MenuGUI::clickConnectButton, this);

    
    // Chat panel =============================================================

    const FloatRect chatListRect = { 0.0f, 0.0f, 1.0f, 0.95f };
    const FloatRect chatBoxRect = { 0.0f, 0.95f, 1.0f, 1.0f }; 

    Panel & chatPanel = *sheet.createPanel(layoutRect(chatPanelRect, sheetDim));
    QuickGUI::Rect chatDim = chatPanel.getClientDimensions();
    chatDim.position = QuickGUI::Point::ZERO;

    List & chatList = *chatPanel.createList(layoutRect(chatListRect, chatDim));
    add("lobbySheet.chatList", chatList);
    chatList.setEnabled(false); //don't want user selected list items
    chatList.setRelativeOpacity(0);

    TextBox & chatBox = *chatPanel.createTextBox(layoutRect(chatBoxRect, chatDim));
    add("lobbySheet.chatBox", chatBox);
    chatBox.addWidgetEventHandler(WIDGET_EVENT_KEY_DOWN, &MenuGUI::enterChatMessage, this);


    // View tab (on side) =====================================================

    TabControl & viewTabControl = *sheet.createTabControl(layoutRect(viewTabRect, sheetDim));
    add("lobbySheet.viewTabControl", viewTabControl);

    seg[0] = TextSegment("micross.18", ColourValue(0.3f, 0.5f, 0.3f), "Players");
    TabPage & playerTab = *viewTabControl.createTabPage(seg, PLAYER_TAB_INDEX);
    playerTab.setScrollable(false);

    seg[0] = TextSegment("micross.18", ColourValue(0.5f, 0.3f, 0.3f), "Scenario");
    TabPage & scenarioTab = *viewTabControl.createTabPage(seg, SCENARIO_TAB_INDEX);
    scenarioTab.setScrollable(false);

    viewTabControl.selectTabPage(PLAYER_TAB_INDEX);
    QuickGUI::Rect viewTabControlDim = playerTab.getClientDimensions(); //yes indeed
    viewTabControlDim.position = QuickGUI::Point::ZERO;


    // Player tab widgets =====================================================
    
    //TODO: see if it is the right approach to make an actual List for the player list
    /*const FloatRect & playerListRect = chatListRect;
    List & playerList = *playerTab.createList(layoutRect(playerListRect, viewTabControlDim));
    add("lobbySheet.playerList", playerList);
    playerList.setEnabled(false);*/


    // Finalize ===============================================================

    setLobbySideVisibility(false);
}

void MenuGUI::initReplaySheet()
{
    // Sheet ==================================================================

    const FloatRect allSheet = { 0.05f, 0.05f, 0.95f, 0.95f };
    const QuickGUI::Size maxSheetSize(1024, 768.0f);
    Sheet & sheet = *createSheet(allSheet, AA_CENTER, AA_CENTER, &maxSheetSize);
    add("replaySheet", sheet);

    QuickGUI::Rect sheetDim = sheet.getClientDimensions();
    sheetDim.position = QuickGUI::Point::ZERO;

    // Replay List ============================================================

    const FloatRect replayListRect = { 0.0f, 0.1f, 1.0f, 1.0f };
    List & replayList = *sheet.createList(layoutRect(replayListRect, sheetDim));
    add("replaySheet.replayList", replayList);
    replayList.addListEventHandler(LIST_EVENT_SELECTION_CHANGED, &MenuGUI::changeReplayListSelection, this);

    // Buttons ================================================================

    const FloatRect buttonsPanelRect = { 0.0f, 0.0f, 0.34f, 0.1f };
    Panel & buttonsPanel = *sheet.createPanel(layoutRect(buttonsPanelRect, sheetDim));
    QuickGUI::Rect buttonsPanelDim = buttonsPanel.getClientDimensions();
    buttonsPanelDim.position = QuickGUI::Point::ZERO;

    const FloatRect startButtonRect = { 0.0f, 0.0f, 0.5f, 1.0f };
    Button & startButton = *buttonsPanel.createButton("Start", layoutRect(startButtonRect, buttonsPanelDim));
    startButton.addWidgetEventHandler(WIDGET_EVENT_MOUSE_BUTTON_UP, &MenuGUI::clickReplayStartButton, this);

    const FloatRect cancelButtonRect = { 0.5f, 0.0f, 1.0f, 1.0f };
    Button &cancelButton = *buttonsPanel.createButton("Back", layoutRect(cancelButtonRect, buttonsPanelDim));
    cancelButton.addWidgetEventHandler(WIDGET_EVENT_MOUSE_BUTTON_UP, &MenuGUI::clickReplayCancelButton, this);
}

void MenuGUI::initConnectWindow()
{
    //create connection window
    const QuickGUI::Size connectWindowSize(400.0f, 300.0f);
    Window & window = *get<Sheet>("lobbySheet").createWindow("Connect", QuickGUI::Rect(QuickGUI::Point::ZERO, connectWindowSize));
    add("connectWindow", window);
    window.setResizeFromAllSides(false);
    window.setVisible(false);

    QuickGUI::Rect windowDim = window.getScrollableContainerWidget()->getClientDimensions();
    windowDim.position = QuickGUI::Point::ZERO; //because QuickGUI position for Window is weird

    // Text fields ============================================================

    const FloatRect addrLabelRect = { 0.05f, 0.05f, 0.20f, 0.15f };
    const FloatRect addrBoxRect = { addrLabelRect.r, addrLabelRect.t, 0.95f, addrLabelRect.b };
    const FloatRect portLabelRect = { 0.05f, 0.20f, 0.20f, 0.30f };
    const FloatRect portBoxRect = { portLabelRect.r, portLabelRect.t, 0.40f, portLabelRect.b };
    const FloatRect usernameLabelRect = { 0.05f, 0.35f, 0.20f, 0.45f };
    const FloatRect usernameBoxRect = { usernameLabelRect.r, usernameLabelRect.t, 0.95f, usernameLabelRect.b };
    const FloatRect passwordLabelRect = { 0.05f, 0.50f, 0.20f, 0.60f }; 
    const FloatRect passwordBoxRect = { passwordLabelRect.r, passwordLabelRect.t, 0.95f, passwordLabelRect.b };

    window.createLabel("Hostname:", layoutRect(addrLabelRect, windowDim));
    TextBox & addrBox = *window.createTextBox(layoutRect(addrBoxRect, windowDim));
    add("connectWindow.addrBox", addrBox);
    addrBox.addText("localhost");

    window.createLabel("Port:", layoutRect(portLabelRect, windowDim));
    TextBox & portBox = *window.createTextBox(layoutRect(portBoxRect, windowDim));
    add("connectWindow.portBox", portBox);
    portBox.addText("5555");

    window.createLabel("Username:", layoutRect(usernameLabelRect, windowDim));
    TextBox & usernameBox = *window.createTextBox(layoutRect(usernameBoxRect, windowDim));
    add("connectWindow.usernameBox", usernameBox);
    usernameBox.addText("Freshmeat");

    window.createLabel("Password:", layoutRect(passwordLabelRect, windowDim));
    TextBox & passwordBox = *window.createTextBox(layoutRect(passwordBoxRect, windowDim));
    add("connectWindow.passwordBox", passwordBox);

    // Buttons ================================================================

    const FloatRect proceedButtonRect = { 0.05f, 0.85f, 0.30f, 0.95f };
    const FloatRect cancelButtonRect = { 0.70f, proceedButtonRect.t, 0.95f, proceedButtonRect.b };

    Button & proceedButton = *window.createButton("Proceed", layoutRect(proceedButtonRect, windowDim));
    add("connectWindow.proceedButton", proceedButton);
    proceedButton.addWidgetEventHandler(WIDGET_EVENT_MOUSE_BUTTON_UP, &MenuGUI::clickConnectProceedButton, this);

    Button & cancelButton = *window.createButton("Cancel", layoutRect(cancelButtonRect, windowDim));
    add("connectWindow.cancelButton", cancelButton);
    cancelButton.addWidgetEventHandler(WIDGET_EVENT_MOUSE_BUTTON_UP, &MenuGUI::clickConnectCancelButton, this);
}

void MenuGUI::clickLaunchTestButton(const QuickGUI::EventArgs & ev)
{
    prepareForPlay(sim::Int(1)); //deterministic test seed
}

void MenuGUI::clickLobbyButton(const QuickGUI::EventArgs & ev)
{
    getManager().setActiveSheet(&get<Sheet>("lobbySheet"));
}

void MenuGUI::clickReplayButton(const QuickGUI::EventArgs & ev)
{
    refreshReplayList();
    getManager().setActiveSheet(&get<Sheet>("replaySheet"));
}

void MenuGUI::clickExitButton(const QuickGUI::EventArgs & ev)
{
    game_.quit();
}

void MenuGUI::clickConnectButton(const QuickGUI::EventArgs & ev)
{
    if (inLobby_) {

        game_.setAsLocal();
        game_.initNet();

        inLobby_ = false;
        get<Button>("lobbySheet.connectButton").setText("Connect...");
        get<Button>("lobbySheet.startButton").setText("Host...");
        setLobbySideVisibility(false);
    }
    else {
        showConnectWindow(false);
    }
}

void MenuGUI::clickConnectStartButton(const QuickGUI::EventArgs & ev)
{
    if (inLobby_) {
        assert(connectAsHost_);

        //start game
        //TODO: check more preconditions
        if (game_.getNetworking().getVars().countClientUsers() >= 2) {
            netmsg::StartGame startGame;
            startGame.set_seed(sim::Int((int)std::time(0)));
            game_.getNetworking().sendToAll(startGame);
        }
    }
    else {
        showConnectWindow(true);
    }
}

void MenuGUI::clickConnectProceedButton(const QuickGUI::EventArgs & ev)
{
    //because this is singlethreaded, our strategy is to set up host or connect while dialog is still open
    //(there's no repaint regardless)

    std::string hostname = get<TextBox>("connectWindow.addrBox").getText().asUTF8();
    if (hostname.empty() && !connectAsHost_) {
        insertChatLine("You must fill in a host name");
        return;
    }

    std::string username = get<TextBox>("connectWindow.usernameBox").getText().asUTF8();
    if (username.size() < 4) { //TODO: make better check including types of chars
        insertChatLine("Invalid or too short user name");
        return;
    }

    std::string password = get<TextBox>("connectWindow.passwordBox").getText().asUTF8();

    unsigned port;
    try {
        port = boost::lexical_cast<unsigned>(get<TextBox>("connectWindow.portBox").getText().asUTF8());
        if (port > 0xffff) {
            throw boost::bad_lexical_cast();
        }
    }
    catch (boost::bad_lexical_cast &) {
        insertChatLine("Bad port number");
        return;
    }

    if (connectAsHost_) {
        game_.setAsServer(username, password, port);
    }
    else {
        game_.setAsClient(username, password, hostname, port);
    }

    try {
        game_.initNet(); //TODO: make boolean and return status rather than exception, Game must manage state
    }
    catch (net::NetException & e) {
        insertChatLine(e.getDescription());
        return;
    }

    //make GUI changes
    inLobby_ = true;
    get<Window>("connectWindow").setVisible(false);
    get<Button>("lobbySheet.startButton").setEnabled(connectAsHost_);
    get<Button>("lobbySheet.startButton").setText("Start Game");
    get<Button>("lobbySheet.connectButton").setEnabled(true);
    get<Button>("lobbySheet.connectButton").setText("Disconnect");
    setLobbySideVisibility(true);
    updateLobbySide();
}

void MenuGUI::clickConnectCancelButton(const QuickGUI::EventArgs & ev)
{
    get<Window>("connectWindow").setVisible(false);
    get<Button>("lobbySheet.startButton").setEnabled(true);
    get<Button>("lobbySheet.connectButton").setEnabled(true);
}

void MenuGUI::enterChatMessage(const QuickGUI::EventArgs & ev)
{
    const KeyEventArgs & keyEv = dynamic_cast<const KeyEventArgs &>(ev);
    if (keyEv.scancode == KC_RETURN && inLobby_) {
        assert(keyEv.widget == &get("lobbySheet.chatBox"));

        netmsg::ChatMessage chatMsg;
        chatMsg.set_receiver(net::SERVER_ID); //means all receive
        chatMsg.set_text(get<TextBox>("lobbySheet.chatBox").getText().asUTF8());
        game_.getNetworking().sendToUser(chatMsg, net::SERVER_ID);

        get<TextBox>("lobbySheet.chatBox").clearText();
    }
}

void MenuGUI::clickReplayStartButton(const QuickGUI::EventArgs & ev)
{
    List & list = get<List>("replaySheet.replayList");
    if (list.getSelection().size() == 0) {
        return;
    }

    const std::string & path = replayPaths_[list.getSelection().front()->getIndex()];

    sim::WorldManager & worldMan = game_.getWorldManager(); //Save because "this" gets deallocated...
    game_.queuePresentation(new presentation::WorldPresentation(game_, path));
}

void MenuGUI::clickReplayCancelButton(const QuickGUI::EventArgs & ev)
{
    getManager().setActiveSheet(&get<Sheet>("menuSheet"));
}

void MenuGUI::changeReplayListSelection(const QuickGUI::EventArgs & ev)
{
    //just make sure there no "explaining items" are selected

    List & list = get<List>("replaySheet.replayList");
    assert(list.getSelection().size() <= 1);

    if ( list.getSelection().size() == 0) {
        return;
    }
    
    if (list.getSelection().front()->getIndex() < int(replayPaths_.size())) {
        //this is a valid replay element (matched by a path)
        return;
    }

    //this is an unselectable help element, deselect it
    list.clearSelection();
}

void MenuGUI::showConnectWindow(bool host)
{
    get<Window>("connectWindow").center();
    get<Window>("connectWindow").setVisible(true);
    get<Button>("lobbySheet.connectButton").setEnabled(false);
    get<Button>("lobbySheet.startButton").setEnabled(false);
    get<TextBox>("connectWindow.addrBox").setEnabled(!host);
    connectAsHost_ = host;
}

void MenuGUI::setLobbySideVisibility(bool visible)
{
    get<TabControl>("lobbySheet.viewTabControl").setVisible(visible);
    get<Panel>("lobbySheet.smallMapPanel").setVisible(visible);
    get<Panel>("lobbySheet.smallSettingsPanel").setVisible(visible);
}

void MenuGUI::updateLobbySide()
{
}

void MenuGUI::refreshReplayList()
{
    List & list = get<List>("replaySheet.replayList");

    //reset
    list.clearItems();
    replayPaths_.clear();

    //enumerate replays
    using namespace boost::filesystem;
    try {
        const path replayDirectory(getBundlePath() + file::REPLAY_DIRECTORY);
        for (directory_iterator it(replayDirectory), end; it != end; ++it) {
            if (is_directory(*it)) {
                continue;
            }

            if (extension(*it) != file::REPLAY_EXTENSION) {
                continue;
            }

            if (basename(*it) == file::TEMP_REPLAY_PREFIX) {
                continue;
            }

            savemsg::ReplayFileHeader header;
            try {
                file::MessageInputFile replay(it->string(), file::REPLAY_MAGIC);
                replay >> header;
            }
            catch (file::MessageFileException &) {
                continue;
            }

            replayPaths_.push_back(it->string());
            list.createTextItem(header.dateandtime() + " - " + basename(*it));
        }
    }
    catch (filesystem_error &) {
        list.createTextItem("There was an error while searching for replays");
    }

    //finalize
    if (list.getNumberOfItems() == 0) {
        list.createTextItem("No file with " + file::REPLAY_EXTENSION + " extension found in replays subdirectory");
        list.setEnabled(false);
    }
    else {
        list.setEnabled(true);
    }

    list.createTextItem("-------------------------------------");
    list.createTextItem("Put a replay file of an up-to-date version in the replays subdirectory to make them appear here");
    list.createTextItem("A file called " + file::TEMP_REPLAY_PREFIX + file::REPLAY_EXTENSION +
        " is saved after every game; rename this file to keep the replay");
}

void MenuGUI::insertChatLine(const std::string & text)
{
    //TODO: make cases for other sheets...
    const int MAX_ITEMS = 100;
    List & list = get<List>("lobbySheet.chatList");
    ListTextItem & item = *list.createTextItem(text);
    list.scrollChildIntoView(&item);
    
    if (list.getNumberOfItems() > MAX_ITEMS) {
        list.destroyItem(list.getItem(0));
    }
}

void MenuGUI::prepareForPlay(sim::Int seed)
{
    //TODO: rewrite or remove this function, had to remove most of it anyhow
    sim::WorldManager & worldMan = game_.getWorldManager(); //Save because "this" gets deallocated...
    game_.queuePresentation(new presentation::WorldPresentation(game_, seed, "hell"));
}
}; //gui
}; //spelprog2